分类
联系方式
  1. 新浪微博
  2. E-mail

Maeiee Weekly No.8:给红米 9A 编译 Android 系统

介绍

让手机运行自己编译的 Android 系统,是我的一个愿望。

当年刷机还火,我就有这想法,无奈没学会……直到现在,已经没人刷机了。

但是我还是对它感兴趣,于是本周加把劲,希望能在我的 红米 9A 上,成功运行自己编译的 Android 系统。

本文适合于对 Android 系统感兴趣,但是没有相关经验的同学进行入门。

周报改版

前 7 期 Weekly 对我的帮助:过去我长期闭门造车,自己成为井底之蛙而不自知。7 周看了约 100 篇技术文章,让我打开眼界。我很庆幸自己的这次成长。

但我随之发现,仅仅读文章过于浮于表面。原本的过程时:阅读-消化-吸收-分享。由于人的懒惰天性,逐步变为阅读-分享,效果大打折扣,浮于表面。求真知需要 get hands dirty,这是真正的乐趣所在。

所以,从第 8 期 Weekly 开始改版了:每周定一个可实践、具有足够挑战性的主题。我的思路是:把自己扔进水里,如果没有淹死,那就是会游泳了。

维护方式也变了:周初会尽快发布,周中不断 Update,临近周末开始成文,最后结合感想与技术,生成一篇高质量周报。

Android 系统

为什么对 Android 系统感兴趣?我发现现在的高科技都用在手机上了,集成度又高,性价比又高。同时,手机更新换代非常快,大家都有一大堆淘汰手机。这些在我看来都是宝贵的资源。

终极理想:移动 GNU/Linux 设备

研究 Android 系统,并非是对 Android 系统感兴趣,而是对怎么在手机上运行 GNU/Linux 更加感兴趣。

还有一点让我感兴趣的:怎么在 GNU/Linux 上以原生方式运行 Android APP。

目前,WSA、Anbox、WayDroid 运行的方式,都是基于完整 Android 系统镜像,容器化方式打包运行。我理想中的方式不是这样,而是将 Android 的协议完全融入 Linux Desktop 生态。其实就是,把 Android 以 FSF 方式重新实现一遍。道阻且长,就当我在发梦。

为什么有这个想法?对现在的手机生态不满意。

路线图

从头建立知识体系,没有线性路线图。遇到不会的概念,先搞懂,概念会带出其它概念,由点及面,如此循环,最终一副体系图跃然脑中。以下路线图是我事后梳理的:

  1. 基础知识了解
  2. 分区概念
  3. Custom Recovery、备份相关知识
  4. 刷预编译 ROM、刷坏了怎么恢复
  5. 自己编译系统并刷入

最终目标(给红米 9A 编译 Android 系统)没有达成,远比我想得复杂。整个过程体验也不太好,大多数问题都不是技术带来的,都是人为造成的障碍。

这种障碍让我更加认可 PostmarketOS 和 Halium 等项目的重要意义。软件领域任何问题都可通过一层抽象抹平,这些技术就是消除这篇黑暗森林的那一束光。

十万个为什么

一头扎进一片陌生领域,会有十万个为什么等着自己。对我来说,这是最有乐趣的。我以求知为乐,就像一个大蛋糕摆在我面前。这些为什么有的搞懂了,有的还没搞懂:

recovery Magisk A/B device Dynamic Partitions mkbootimg Soong
vbmeta META 模式 bootrom protection MTKClient zImage VNDK
GSI Fastboot TWRP Recovery 基带分区 zImage-dtb msm-4.19平台
boot.img system.img Android 内核 selinux vbmeta.img RIL
Unified Device Tree

不知道的还很多,没关系,慢慢来。

Bootloader 解锁

bootloader 是设备启动时执行的第一个程序。通过 bootloader 可以进入不同启动模式,比如选择进入系统还是进入 Recovery。

手机的 bootloader 默认是被锁定的,锁定意味着不允许用户进行任何定制。如果想瞎折腾(刷 Custom Recovery、Custom ROM、Root 手机),就需要解锁 bootloader。

解锁 bootloader 是有风险的

  1. 设备的保修就失效了
  2. 不再收到官方的OTA更新
  3. 设备有变砖的风险

如果我花几千块买了一台新手机,还是不舍得解锁 bootloader 的……所以,对我来说,还是用淘汰手机、廉价机、二手淘来的更合适一些。

具体解锁方式可按照机型参照相关教程。需要注意的是,小米手机解锁 Bootloader 需要绑定小米帐号,并使用 Mi Unlock Tool。

注:《How to unlock bootloader on Xiaomi Redmi 9 Prime》

fastboot

fastboot 是 Android 手机的一种模式,在该模式下能够对各个分区进行烧录。在电脑上也有同名 fastboot 工具与之对应。

最常用的用途,就是通过 fastboot,将 Custom Recovery 刷入 recovery 分区。

按照固定组合键启动手机,就能进入 fasboot 模式,比如在红米 9A 是音量下+电源键,或者通过 adb 命令:adb reboot bootloader。(注意,在小米手机上还有一个 fastbootd 模式,不是一回事)。

Recovery

Recovery 既是一个分区,也是一种模式,顾名思义,用于手机恢复。手机自带的 Recovery 没有定制能力,需要刷入第三方的 Recovery 才能获取当强大的刷机、root 能力。

Recovery 本身是 Android 开源代码的一部分,也是开源的,各个第三方的 Recovery 都根据该开源代码衍生而来。其中,最为著名的是 TeamWin Recovery Project(TWRP),它是最流行的 Android custom recovery。基于 TWRP 由衍生出一些流行的 Recovery,如 OragneFox Recovery。这些会在后文专门小节中介绍。

通过 fastboot 刷 Recovery 的命令是:

fastboot flash recovery twrp.img

通过 fastboot 重启到 Recovery 的命令是:

fastboot reboot recovery

img 镜像

在上面的命令汇总,twrp.img 是 TWRP 的镜像文件,以 .img 格式后缀,它是是一种特殊的 Android 定制格式。

通过 fastboot 进行刷写的分区,都是传入这种格式的镜像。

Android 手机分区

Android 生态以其碎片化著称,所谓碎片化,就是乱,总是变,并且各家厂商不一致。在探索 Android 系统过程中,分区的概念让我第一次感受到这种混乱与窒息。我的大部分困惑,都与分区有关。

作为一个使用 Arch Linux 近十年的人,在 PC 上我能很容易从 0 组装出个桌面环境出来:分区、格式化、安装系统、安装桌面环境。哪怕是手动编译内核,也十分方便。

来到 Android 上真的把我整蒙逼了。下面将介绍我已掌握的分区知识,但这只是冰山一角。

两种分区模式

随着 Android 系统的演进,分区方式总的可以分为两种,传统的 A-only 分区和新的 A/B 分区。

A、A/B 的含义,类似于飞机、航天器当中有两套电脑系统,一套坏了可以立即切换到另一套。

A 指的是只有一套,A/B 指的是磁盘里面有两套分区,一套里面的系统乱了,可以立刻切换到第二套。当然,更加常用的场景,是用户使用某一套,然后在另一套分区中进行无缝 OTA。

这事也让我挺蒙的,我在 Arch Linux 里面升级系统的时候,都是一边升一边用就 OK。当然,早年的 Arch Linux 确实有滚挂这一说,但这已经是历史往事了。

A-only 分区

又称 non-A/B,传统分区结构,只有一套,不再赘述。常见分区包含以下:

分区 说明
bootloader 设备启动首先进入 bootloader 程序

三种模式:Android 系统模式、recovery 模式、fastboot 模式

boot 每次启动时自动加载到文件系统根部的文件,包括 Android 系统 Kernel 和 Ramdisk
system Android 系统可执行程序、库、系统服务、App,挂载到 system/ 目录下
vendor 厂商私有可执行程序、库、系统服务、App,对 system 的补充
userdata 用户存储空间,存放用户安装的 App 数据,挂载到 data/ 目录下
recovery recovery 系统的 kernel 和 ramdisk
cache 系统升级、OTA 包等缓存
misc 主要用于 Android 系统和 bootloader 通信

这些分区虽然多,也算规整,但这只是 Android 早期的情形。红米 9A 上的分区,比这个要复杂的多。

注1:内核启动过程,内核启动后,运行第一个用户态程序 init,加载 Android 系统。

注2:双清就是清 userdata 和 cache

注3:OTA 时,升级包下载到 cache 分区

注4:参考文章《Android系统分区与升级 - 知乎

A/B 分区

Android O 之后引入的新分区结构。将系统分区分为 A、B 两个槽(Slot)。手机启动时从其中一个槽启动。一旦一个槽出问题,还有另一个槽可用。A/B 分区不再需要为 cache 预留足够空间。

用途:无缝 OTA,用户使用 A 槽,在 B 槽升级,完成后重启运行 B 槽。OTA 升级失败不会影响当前槽的系统。

随着 A/B 分区概念的引入,分区功能发生了一些扩充:

分区 说明
bootloader 添加根据 FLAG 启动对应槽的能力
boot_a/boot_b 包含 kernel 和 recovery 的 ramdisk,有两套。

recovery 打包进 boot 分区,不再需要 recovery 分区。

recovery 不再负责 OTA(由系统 update_engine 服务负责),仅负责双清。

system_a/system_b 功能同 system,只是分为两个槽
vendor_a/vendor_b 功能同 vendor,只是分为两个槽
userdata 不变,不区分 A/B
misc 不变,不区分 A/B
persist 存储持久化数据,OTA、双清都不会清,不区分 A/B

注1:参考文章《Android系统分区与升级 - 知乎

分区的多样性

A 和 A/B 尽管是两套,但也还是一脉相承。可是,随着 Android 的发展,诞生了各种新的概念,加上各个厂商各自的创意。所以,我参照生物物种的多样性,将本节命名为分区的多样性。

比如,还有一些额外分区:

分区 说明
odm 原始设计制造商(ODM)对 system-on-chip(SoC)供应商的 board-support packages(BSP)的定制
odm_dlkm 专门用来存储 ODM 内核模块的
metadata 当设备使用元数据加密时,该分区用于存储元数据加密密钥
radio 存放 radio image
tos 存储了 Trusty 系统的二进制镜像,只有在设备包含 Trusty 时才使用

这些分区大眼一看,就知道每个背后都不简单。更加不幸的是,我把红米 9A 的分区打出来之后,发现跟上面又对不上了。

查看红米 9A 的分区

有好多种办法可以查看手机分区,不同方法看到的分区也不一样:

在系统中,使用 cat /proc/mounts 能看到分区表(精简掉挂载参数之后):

dandelion:/proc $ cat mounts
# 分区                                          # 挂载位置
/dev/block/dm-3                                 /
/dev/block/platform/bootdevice/by-name/md_udc   /metadata
/dev/block/dm-4                                 /vendor
/dev/block/dm-5                                 /product
/dev/block/platform/bootdevice/by-name/userdata /data
/dev/block/platform/bootdevice/by-name/cache    /cache
/dev/block/platform/bootdevice/by-name/protect1 /mnt/vendor/protect_f
/dev/block/platform/bootdevice/by-name/protect2 /mnt/vendor/protect_s
/dev/block/platform/bootdevice/by-name/nvdata   /mnt/vendor/nvdata
/dev/block/platform/bootdevice/by-name/nvcfg    /mnt/vendor/nvcfg
/dev/block/platform/bootdevice/by-name/persist  /mnt/vendor/persist
/dev/block/bootdevice/by-name/cust              /cust
/dev/block/loop2                                /apex/com.android.tzdata@292500001
/dev/block/loop2                                /apex/com.android.tzdata
/dev/block/loop3                                /apex/com.android.media@292000301
/dev/block/loop3                                /apex/com.android.media
/dev/block/loop4                                /apex/com.android.resolv@290000000
/dev/block/loop4                                /apex/com.android.resolv
/dev/block/loop5                                /apex/com.android.conscrypt@290000000
/dev/block/loop5                                /apex/com.android.conscrypt
/dev/block/loop6                                /apex/com.android.runtime@1
/dev/block/loop6                                /apex/com.android.runtime
/dev/block/loop7                                /apex/com.android.apex.cts.shim@1
/dev/block/loop7                                /apex/com.android.apex.cts.shim
/dev/block/loop8                                /apex/com.android.media.swcodec@292200001
/dev/block/loop8                                /apex/com.android.media.swcodec

其中:

除了物理文件系统外,也会挂载一些虚拟文件系统:

  • /dev、/proc、/sys、/dev/pts、/dev/socket、/devpts 都是由 init 进程创建的
  • tmpfs 文件系统:虚拟内存文件系统,把文件放在内存里,临时内容,速度惊人
  • devpts 文件系统:为伪终端提供了一个标准接口
  • sysfs 文件系统:挂载在 /sys 目录下,把设备和总线组织成文件,供用户空间访问
  • 参考:android的init过程分析_windskier的博客-CSDN博客

当我安装 OragneFox 这个 Custom Recovery 后,看到的是如下的分区:

名称 大小(MB) 说明 是否备份 备注
Data 4327.62 存储用户文件 Y wipe 这个相当于恢复出厂
Boot 64 启动分区包含内核 Y
Cache 11.16 缓存分区 N
Cust 832 放广告? Y 只有国产手机有这个分区
Boot Logo 8MB Y
nvcfg 32 Mediatek 基带分区 Y
nvdata 64 Y
NVRAM 64 Y
Persist 48 Y
protect_f 8 Y
protect_s 10.87 Y
Recovery 64 Recovery Y
Internal Storage 6926.09 内部存储 N 存放备份文件的分区

没法同时写入和备份

VBMeta 8 Verified Boot Y
VBMeta System 8 Y
VBMeta Vendor 8 Y
Super(system vendor product) 4608 动态分区 Y 系统分区

可以看到,相较于前面又多出了几个分区,比如:

动态分区

Android 10 支持动态分区(dynamic partitions)。将多个分区(system、product、endor、odm 等)合并成一个 super 分区。用户空间的分区系统,可以通过 OTA 来创建、调整、销毁分区。

动态分区不能用 fastboot flash system system.img 刷 System 了,只能 Super 一起刷:

fastboot flash super super.img

Linux 内核不再能运行 Android 10 的设备上挂载逻辑系统分区,因此这一操作由第一阶段的 init 处理。

当动态分区遇到 A/B 槽:super 分区不区分 A/B 槽,而是 super 中包含了 A、B 两套分区。

注1:参考文章《Android系统分区与升级 - 知乎

System-as-root

刚有点理解动态分区,阅读文章时发现过去还有一种 System-as-root 的概念,权当了解了。

Android N/O 时引入,当时还没有 A/B 分区、动态分区概念。简称 SAR,rootfs 不再位于 boot.img 的 ramdisk 中,而是与 system 合并放在 system.img 中。效果:系统启动 Android 系统,kernel 将直接挂载 system.img 作为 rootfs。

Android 强制使用 SAR。SAR 有两种:

  1. legacy system-as-root(LSAR):非动态分区,Android Q 以前使用
  2. two-stage-init(2SI):Android Q 引入,支持动态分区和非动态分区

注1:参考文章《Android系统分区与升级 - 知乎

SSI

Shared System Image(SSI):共享系统镜像。同一个 Android 版本,各个设备的 system.img 都由该版本原生 AOSP(或厂商定制)编译出,多产品共同使用,与具体硬件无关。将与硬件、型号有关的代码,放到其它分区中。为了进一步让 Android 和各厂商软件解耦,提高大版本升级的向后兼容。

注:这是一种 Google 为了解决碎片化引入的手段。

分区方式:

  • system(SSI):通用 Android 系统,不同厂商、不同型号设备通用
  • product:特定产品有关,系统定制化
  • vendor:厂商对系统的定制
  • odm:可选分区,SoC 附加程序

注1:参考文章《Android系统分区与升级 - 知乎

文档:

Android OS Core Topics | Android Open Source Project

Project Treble

Project Treble Android 8.0 引入,解除了之前 Android 系统中驱动与系统版本的“挂钩”机制。允许厂商推出长期兼容未来新版本的驱动,保证能在以后的新版本 Android 中,无需修改也能正常使用。

注:Project Treble 方案比较有名,目前只是进行简单的了解,有待于后续深入挖掘。

支持 PT 需要手机支持内存分区,留出一个专门分区用于系统更新。

Android 拆分为 2 个部分,安装到不同分区:

  1. 特定于硬件的部分(供应商实现),供应商分区中
  2. 通用操作系统部分(Android 操作系统框架),系统分区中

供应商接口 (VINTF) :一种带有版本的接口,对接两个分区作用:在不修改供应商分区的情况下修改系统分区,反之亦然。

原因:交付给用户的 Android 系统,被 SoC 供应商和 OEM 多次定制,一旦官方不维护了,升级困难。实现 Treble 标准后,老设备也能升级系统(向后兼容)

文档:

VBMeta

VBMeta 是启动校验,与 Android 的 Verified Boot 机制有关。Android 8 之后实现了 Android Verified Boot(AVB)。Verified Boot 会校验手机系统完整性,刷过 Custom Recovery 之后,系统发生了变化,会导致校验失败。

可以通过刷入与设备对应的 VBMeta,来关闭 Verified Boot 校验功能,具体命令如下:

fastboot --disable-verity --disable-verification flash vbmeta vbmeta.img

手动刷入 vbmeta.img 的场景,大多数是为了关闭 Verified Boot,否则 TWRP 无法安装。

注1:[CLOSED] What is "vbmeta.img" ? | XDA Forums

注2:Android Verified Boot | Android Open Source Project

注3:Android Verified Boot 2.0

Android verified boot 2.0 vbmeta 数据结构解析 - 简书

TWRP Recovery

关于 Android 分区暂且告一段落,下面进入 Custom Recovery。前文中对 Custom Recovery 已做过介绍,是 Android 系统爱好者最经常打交道的工具了。

Custom Recovery 会覆盖调系统自带的 recovery 环境,为用户提供定制能力,比如:刷自定义 ROM、系统备份、通过 Magisk root 设备。

TWRP 是目前最流行的 Custom Recovery 方案,支持大量设备,由于开源,开发者也可以非官方地移植到其他设备。同时由于易于扩展,有许多 fork 和功能增强的衍生 Recovery,同样非常流行。

安装流程

大体的安装流程如下:

  1. 解锁 bootloader:会破坏保修,打开开放性后,自己瞎捣鼓有可能让设备不稳定,甚至变砖,需要慎重考虑风险,并自行承担后果
  2. 安装准备:
    1. 寻找适配机型的 TWRP,先去官网找 Official,如果没有去搜非官方移植
    2. A-only 和 A/B 分区安装方式不同
    3. 如何判断是哪种?getprop ro.build.ab_update
      • 返回 true 表示 A/B partitions
      • 没返回表示 A-only devices
  3. A-only 安装
    1. 设备重启到 bootloader:adb reboot bootloader
    2. 刷入 twrp:
      • fastboot flash recovery twrp.img
      • fastboot reboot
    3. 一旦 TWRP 启动后,他会给原生 ROM 打 patch,阻止它替换 TWRP
  4. 注:也可以临时启动 twrp 但是不刷:fastboot boot twrp.img
  5. A/B 安装
    1. recovery 环境和 boot image 被 fused 在一起,需要先临时启动 TWRP,然后在 custom recovery 中永久安装。
    2. Step2:设备重启到 bootloader:adb reboot bootloader
    3. Step3:也可以临时启动 twrp:fastboot boot twrp.img
    4. Step4:把 TWRP 放入 SD 卡中:adb push twrp.img /sdcard
    5. Step5:进入 TWRP,在底部点击 Install Recovery Ramdisk,选择拷进去的 twrp.img,滑动安装并重启,安装完成。
  6. 注:三星手机根别的不一样,需要注意

安装完成后,验证是否安装成功:按照组合键或者 adb reboot recovery,看看嫩不能正常进入 TWRP。

注:TWRP 还有官方 App:提醒 TWRP 更新,如果手机 root 了,可以直接在手机上更新。

具体的安装流程,可自行根据手中设备型号,搜索具体的教程。

注:《How to install TWRP on your Android smartphone in easy-to-follow steps

Install 安装功能

下面小节中,对 TWRP 的常用功能进行介绍。本节介绍 install 安装功能:

Install 用于刷 zip 文件或者 img 文件。比如自定义 ROM、自定义内核、用于 root 手机的 Magisk 包。打开后进入文件管理器,选择镜像进行刷入。

Wipe 清除功能

对设备进行 factory reset 数据清除操作。有细化控制,支持清除特定分区。一般安装自定义 ROM 前都要执行清除操作。

注意,谨慎操作:有可能把系统分区抹掉,最后手机里没有操作系统,或者抹掉内部存储,数据丢失。

Backup 备份功能

对于折腾来说,备份功能尤为重要。TWRP 的备份功能可以对手机进行完全备份,是备份手机的最佳方式。变砖之后可以用他恢复。

最佳实践:辖捣鼓之前先用 TWRP 完全备份一遍。

尤其是一些关键分区,数据损坏了就再也找不回来了。比如 EFS 分区:IMEI 号丢了还能用它恢复。

Restore 恢复功能

Backup 会将数据备份到一个文件中,Restore 则根据这些文件,把数据刷回分区中。

如果遇到把系统搞坏,比如 bootloop 或者其他问题,恢复就派上用场了。

Mount 挂载功能

每个手机都有多个分区,通过挂载,控制哪些分区能够被 TWRP 访问。

常用的分区比如,System 分区用于安装系统,Data 分区存储用户文件,Cache 分区缓存数据。

Settings 设置功能

TWRP 设置

Advanced 高级功能

里面包含了一些高级功能,比如 sideload、terminal 等。

Reboot 重启

重启到手机的不同模式,可以选择是进系统,还是去 fastboot。

OrangeFox Recovery

是最流行的自定义 recoveries 之一,带有特色附加功能、修复。

特性:

  • 与 Teamwin 最新改动同步
  • Material design 2 设计
  • 实现支持 Flyme 和 MIUI OTA,以及自定义 ROM 基于块的增量 OTA
  • 包括多种定制、多种扩展、密码保护
  • 内置的补丁,如 Magisk 和密码重置补丁
  • 完全开源、更新活跃

为什么要搞 OrangeFox Recovery?

我们从2018年初开始运作。从那时起,我们已经改善了 Recovery 的质量、稳定性和设备支持。今天,OrangeFox 在稳定性、UI设计和用户体验方面处于领先地位。安装 OrangeFox 意味着与最新的代码和最快的修复。

OrangeFox Recovery 最初是为小米红米 Note 4X Snapdragon(mido)设计的。现在我们支持 50 多个设备,在我们的官方下载服务器上有超过 500 万次的下载。

OrangeFox 对红米 9A 有官方实现,XDA 发布贴:《[OFFICIAL][RECOVERY] The OrangeFox Recovery Project [R11.1] | XDA Forums

红米 9A 采用的是 A-only 分区方式。

支持设备:Redmi 9A (dandelion)、Redmi 9C (angelica)、POCO C3 (angelicain)、Other garden device (Xiaomi MT6765 / MT6762 With Dynamic Partitions)

相关源码:garden 设备源码OrangeFox 源码OrangeFox App

注:

  1. MTK-bypass/bypass_utility:Small utility to disable bootrom protection(sla and daa)
  2. I was able to flash the stock ROM once again using the software MTKClient

刷 OragneFox Recovery

[maxiee@maxiee-hpbook RedMi9A]$ adb reboot bootloader
[maxiee@maxiee-hpbook RedMi9A]$ sudo fastboot flash recovery recovery.img 
[sudo] password for maxiee: 
Sending 'recovery' (65536 KB)                      OKAY [  1.673s]
Writing 'recovery'                                 OKAY [  0.898s]
Finished. Total time: 2.573s

刷完之后,重启,发现还是官方的 Recovery。按照这种方法能进去 OragneFox 了:

[maxiee@maxiee-hpbook RedMi9A]$ sudo fastboot flash recovery recovery.img 
Sending 'recovery' (65536 KB)                      OKAY [  1.657s]
Writing 'recovery'                                 OKAY [  0.897s]
Finished. Total time: 2.558s
[maxiee@maxiee-hpbook RedMi9A]$ sudo fastboot reboot recovery
Rebooting into recovery                            OKAY [  0.001s]
Finished. Total time: 0.253s

Recovery 备份

先备份再折腾!

在 OragneFox Recovery 中,我把除了 Cache 和 Internal Storage 外的分区都勾选上了,并拷贝出来存放好,以后瞎捣鼓坏了就靠它恢复了。

(为啥不勾 Internal Storage,这个是内部存储,备份系统最终生成的文件就在这个分区上,没法在这个分区上同时又写入又备份)

需要注意的是,里面有一些特殊分区,当手机没出问题的时候,不要去恢复这些分区。只有当不小心把特殊分区搞坏了,手机已经不正常了,这时用特殊分区的 backup 单独恢复,来抢救一下。

哪些不需要备份:cache、recovery 不需要备份

android_secure、sd-ext 如果有,也可以备份一下。

dm-verity 分区用于启动时校验系统分区数据完整性,dm-verity 的启用会阻止 TWRP 进行系统恢复。

注:What should I back up in TWRP?

哪些分区是特殊分区?我查到一些,但不限于以下分区:

TWRP刷机之前怎么备份Persist和EFS分区,防止重要参数丢失-ROM乐园官网

  • persisit 分区:
    • 包含DRM相关文件、注册表以及wifi、蓝牙、mac的地址
    • 损坏:wifi、蓝牙无法使用,或者重力感应失灵、相机打开异常等现象
    • @ZRGNiX 指导:persist 负责存放各种传感器的出厂校准数据(比如距离传感器),无论A-only还是A/B都有。
  • EFS分区:
    • 用来存取手机IMEI串号、无线网卡MAC地址以及网络设置的重要信息
    • 如果这个分区被清空会出现基带未知、IMEI串号丢失导致手机无信号等现象
  • 备份方式,把这俩都勾上(persisit 和 efs)

NANDroid

很多文章会提到 NANDroid 这个名词,指的是对 NAND flash 进行全盘备份。

但是查阅如何在 TWRP 里 NANDroid 备份,其实指的还是 TWRP 的 Backup 功能。

注:How to Create and Restore NANDroid Backup? - TechSphinx

导出备份文件

备份完成后,内部存储的根目录多一个 Fox 文件夹(OragneFox Recovery)。将它从手机拷到电脑重来,并保存好即可。

刷 Recovery 数据线问题导致传输失败

Sending 'boot.img' (65536 KB) 卡住

遇到问题,卡在这里不动了。好象是线的问题,换了根数据线好了。

红米 9A 手机基本信息

因为要瞎折腾,把相关信息记录下来,方便参考。手机详细数据

设备型号:Redmi 9A,具体型号:M2006C3LC,codename:Xiaomi Dandelion

baseband version:MOLY.LR12A.R3.MP.V107.5.P77

Kernel version:4.9.190-perf-g84308b9

Android 系统版本:10 QP1A.190711.020

MIUI 系统版本:MIUI Global 12.0.10

红米 9A ROM 收集

我在 XDA 论坛上验证了几个自定义 ROM,通过《Redmi 9A ROMs, Kernels, Recoveries, & Other Develop》能够查阅到更多 ROM。

PixelExperience

PixelExperience 为用户带来 Pixel 手机的体验,它基于 AOSP,内置 Google 应用,自带 Pixel 系列软件(launcher, wallpapers, icons, fonts, boot animation)。该系统基于 Android 12.1。需要手机原版系统为 12.0.10,我的原版系统是 MIUI Global 12.0.10,刚好满足。

我在红米 9A 上能够成功刷机并运行,并且整个系统确实跟 Pixel 的手机一样。受限于红米 9A 的机能,系统自身流畅度不高,加上我已经被高刷屏惯坏了,日常用的话总感觉卡卡的。

ROM 地址《[ROM][12.1][UNOFFICIAL] PixelExperience Unified for Redmi 9A/9C/9 Activ [garden] | XDA Forums

哪些工作:Wi-Fi、RIL、Mobile data、GPS、Camera、Flashlight、Camcorder、Bluetooth、Fingerprint reader、Face unlock、Lights、Sound/vibration

哪些不工作:Fingerprint、VoLTE

Device Source code: https://github.com/garden-dev/android_device_xiaomi_garden

Source code: https://github.com/PixelExperience

这个 ROM 还有一个好处,貌似可以薅羊毛:We get free unlimited Google photos backup too!!!

红米 9A 手机有一个通病,刷了自定义 ROM 后通话声音小,我看到好多人都这么说(我自己没有验证过),网上的解决的方法是安装一个 Magisk 插件能够恢复正常音量。

Droidian

Droidian 是一种 GNU/Linux 发行版,基于 Mobian,后者是一种基于 Debian 的发行版。我对这个 ROM 兴趣最大,可惜刷了好几遍都没有成功跑起来。但是我没有放弃,下一期的主题就是让 Droidian 在红米 9A 上跑起来。

ROM 地址:[Linux OS] Droidian Redmi 9A [dandelion][angelica]

Android 内核

Android 内核基于 Linux 内核,在 Linux 之上打了 Android 专用补丁,形成 Android 通用内核(ACK)。

GKI 内核:版本 5.4 及以上的 ACK,支持硬件无关的内核代码和硬件无关的 GKI 模块。

注1:参考《内核概览 | Android 开源项目 | Android Open Source Project

boot.img

启动镜像,用于启动 Android 内核。boot.img 是一种特殊的 Android 定制格式。包括以下部分:

  • boot header:启动参数,与芯片相关
  • kernel:内核,gzipped 压缩
  • ramdisk:最基础的小型文件系统,包括初始化系统所需的全部核心文件,比如 init 程序和 init.rc

玩法:

  1. 更换手机启动图

注1:参考《android boot.img 结构_zhenwenxian的博客-CSDN博客_android boot.img

注2:参考《What is boot.img file in android? - Stack Overflow

注3:参考《HOWTO: Unpack, Edit, and Repack Boot Images | XDA Forums

Kernel Device Tree,简称 dt

ARM 平台 SoC 众多,硬件配置不同。设备树框架是与设备相关的配置文件,保持内核代码树整洁。

  • DTS(Device Tree Source):设备树源码
  • DTB(Device Tree Blob):设备树二进制,通过 DTC 对 DTS 编译而成
    • 芯片级配置:GPU 频率表,GPU 超频卡刷包里面是个 dtb 文件
  • DTC(Device Tree Compiler):设备树编译器,由内核提供
  • DTBO(Device Tree Binary Oerlay):device tree 一部分拆分到 boot 分区,一部分拆分到 dtbo 分区。初衷:芯片厂商只修改内核 dtb,手机厂商只修改 dtbo 分区。
    • 厂商级配置:屏幕、相机,超频刷新率通常改 dtbo 分区

device tree 不开源,有的会放回内核里,有的会作为额外仓库开源提供。

注1:参考 Linux Kernel Device Tree 配置框架_csid_502的博客-CSDN博客

注2:参考 kernel dtb 与 dtbo - AKR社区

感悟:进入新领域如何学地更快?

看完《Partitions Overview》后,我发现只一个分区,就有好多篇章的内容。以我现在逐篇笔记的方式,一周时间内是学不完的。

如何加快速度呢?

  1. 这里面的知识,大多数我都不用不到,里面 20% 的内容是我需要的
  2. 按照笔记大纲方式读文章,尽管学得比较认真,但是速度太慢,把 80% 可略过的内容,也强制看了一遍
  3. 按照自己的思考建立笔记,只记录必要的知识

Source Android Documentation

Android OS Core Topics | Android Open Source Project

  1. Partitions Overview
    • 标准分区
      • boot 分区:包含 kernel image 和 ramdisk,使用 mkbootimg 进行组合
        • 可以使用虚拟分区(virtual partition)直接刷 image,而不用刷新的 boot 分区
          • 什么意思?
        • kernel:
          • kernel 虚拟分区覆盖内核的 zImage、zImage-dtb、Image.gz-dtb
          • 如果提供的开发内核不兼容,需要更新 vendor、system、dtb 分区连同相关内核模块
        • ramdisk:ramdisk 虚拟分区
      • 覆盖操作
        • 确定 eMMC 现有 image 的起始位置,将新 image 拷贝到对应位置
        • 新 image 可能比原来的大
          • 为了腾出空间,bootloader 可以在映像后面移动数据或以报错方式放弃操作
      • system 分区:包含 Android 框架
      • odm 分区:
        • 包含原始设计制造商(ODM)对 system-on-chip(SoC)供应商的 board-support packages(BSP)的定制。
        • 该定制使 ODM 能够替换或定制 SoC 组件,并在硬件抽象层(HAL)上实现特定 SoC 组件、守护程序和 ODM 特定功能的内核模块
        • 这个分区是可选的;通常,它被用来包含定制,以便设备可以为多个硬件 SKU 使用一个 vendor image。详情请见 ODM 分区
      • odm_dlkm 分区:
        • 专门用来存储 ODM 内核模块的
        • 将 ODM 内核模块存储在 odm_dlkm 分区(相对于odm分区),使得更新 ODM 内核模块而不更新 odm 分区成为可能
      • recovery 分区:
        • 存储 recovery image,在 OTA 时被启动
        • 支持无缝更新(seamless updates)的设备,可以将 recovery image 包含在 boot image 的 ramdisk 中(而不是一个单独的 image)
      • cache 分区:
        • 存储临时数据,如果设备使用无缝更新,这个分区是可选的
        • 不需要对于 bootloader 可写入,但是需要是可清除的
        • 分区的大小取决于设备类型和 userdata 的可用空间,通常 50MB-100MB就足够了
      • misc 分区:供 recovery 使用,4KB 或更大
      • userdata 分区:包含用户安装的 App 和数据,包括自定义数据
      • metadata 分区:
        • 当设备使用元数据加密时,该分区用于存储元数据加密密钥
        • 大小为 16MB 或更大
        • 它不被加密,其数据也不被快照
        • 当设备出厂重置时,它会被删除。该分区的使用受到严格限制。
      • vendor 分区:
        • 存放不通过 AOSP 分发的二进制
        • 如果设备不包含专有信息,你可以省略这个分区
      • vendor_dlkm 分区:
        • 存放 vendor 内核模块
        • 使得更新内核模块而不更新 vendor 分区成为可能
      • radio 分区:存放 radio image
      • tos 分区:存储了 Trusty 系统的二进制镜像,只有在设备包含 Trusty 时才使用
    • 动态分区 Dynamic partitions
      • Android 11 以上设备支持动态分区
      • Android 的用户空间分区系统
      • 可以通过 OTA 更新期间创建、调整或销毁分区
      • 详情
    • Android11 的变化
      • 对链接库的限制,新的 Soong image 变体
      • Single System Image (SSI)
        • 新的概念性的 image,包含 system 和 system_ext image
        • 对多种目标设备来说是通用的,可以共享 SSI
        • 跳过构建 system 和 system_ext image 的过程
      • system_ext 分区:
        • 一个新的分区,可以使用系统资源,并可以包括系统模块
        • 扩展 AOSP system 分区的系统模块
        • 捆绑 OEM 或 SoC 特定模块
      • system 分区:用于 OEM 产品的普通 system 镜像
      • product 分区:使用被允许的接口,安装没有与任何其他分区捆绑的产品专属模块
    • VNDK changes
      • Vendor Native Development Kit (VNDK)
      • 安装在系统分区的库,专门为供应商实现其 HAL 而设计
      • Android10 及以下:
        • vendor 分区可以连接到 system 分区的 VNDK 库,但不能链接到 system 分区的其他库
        • product 分区的 Native 模块可以链接到 system 分区的任何库
      • Android11 及以上:
        • product 和 endor 分区都能连接 system 分区内的 VNDK 库,但不能链接到 system 分区的其他库

了解一下,Android 10中的APEX_阿拉神农的博客-CSDN博客(这篇文章五星推荐)

  • APEX,Android Pony EXpress,与 APK 类似,把 Framework 层关键组件变为模块,可以单独升级,类似 APK,后缀为 .apex
  • com.android.runtime:ART 虚拟机
  • runtime:相关 so,libc.so,libdl.so 等
  • com.android.media:多媒体相关 so,libbinder.so,libc++.so 等
  • apex包是被谷老大用来更新系统级功能的就行

2022-08-02 中间规划

成功进入 Custom Recovery 了,并且通过扎实的基础积累,直到要先备份分区然后再折腾。

未来几天的规划:

周三:找适配的编译好的 ROM 刷机尝试

周四、周五:

  • 比较下 AOSP 和 lineageOS 哪个好编译
  • 找出适合的那个进行编译

周六:刷那个 Linux 发行版

周日:完善 Weekly 编写,项目完结

Weekly No.9 下期预告

目标:在红米 9A 上运行 Droidian 系统。

本周的收获是了解了一些 Android 分区知识,并积累了一些 Recovery 经验。最核心的 Custom Andriod 源码并没有学会。如果换一个新领域主题去探索,又变成了浅尝辄止。

Droidian 它既深入,同时我也有兴趣,并且虽然不是常规的 Android 系统,但它是我想要的。

下周,以 Droidian 为契机,希望能有更多的了解。

网络资源

以下是一些零散的文章阅读:

在小米 Redmi 9A/9C/9 Activ 上下載並安裝 AOSP Android 12 - Guidlings

  • 这篇文章是机翻的……
  • adb、fastboot:将设备切换到 bootloader 模式
  • 解锁手机 bootloader
  • 安装 TWRP Recovery
    • 必须安装这个才能安装任意自定义 ROM
    • 先解锁 bootloader,再安装 TWRP Recovery
  • 下载 Android12 ROM:需要用跟手机配套的 ROM
  • 下载 Android 12 GApp:要不然木有 Google 服务

List of Best Custom ROM for Redmi 9A/9C/9 Activ [Updated]

  • launched in June 2020,came with Android 10 Q
  • 介绍了一堆手机 ROM:
    • Lineage OS、Havoc OS、Resurrection Remix、DotOS
    • Mokee OS(魔趣)、CrDroid OS、CarbonROM、ArrowOS
    • Pixel Experience ROM:带来 Google Pixel Experience ROM 体验

Unofficial TWRP Recovery for Redmi 9A | Root Your Phone

红米9A新版刷TWRP_Recovery屏幕不能触摸黑屏怎么办?-ROM乐园官网

  1. 红米9A刷入twrp文件开始出现黑屏或者无限重启不能触摸等
  2. 首先想到降级系统,刷官方线刷包
    1. 受到批次影响,请不要线刷低于12.0.5以下版本,可能会出现彻底黑砖不能启动,需更换主板才能修复。
    2. 成功线刷到旧版一般可解决黑屏不能触摸等问题
  3. 刷最新的 TWRP_Recovery:系统更新快,TWRP Recovery 更新慢,可能会出现新版系统不兼容 TWRP,等待开发者适配,查询 XDA 论坛。
  4. 注:这个问题,我没有遇到

《红米9A刷MIUI国际版实录》

  1. 这是一个线刷教程,对应于原版系统
  2. 注意:国行版本和同硬件的国外版本可能是不同的型号名称
  3. 下载官方的线刷包
  4. 使用 miflash 工具进行线刷
  5. 注意!右下角一定要选择全部删除,不可保留用户数据和加上BL锁,否则刷机后会变砖!

《小米ROM》:由小米发布的任何固件,您可以轻松找到

[超详细教程] 小米/红米线刷国际版MIUI(亲测可用) - 哔哩哔哩

红米9A LineageOS (类原生) 刷机记录报告 - 哔哩哔哩

  1. 引用视频:红米9A成功刷入 Lineage OS (类原生)_哔哩哔哩_bilibili
    1. android_device_xiaomi_dandelion
      1. lineage-17.1 unofficial release
  2. recovery 进入:
    1. 电源 + 音量上
    2. fastboot reboot recovery
    3. fastboot flash vbmeta vbmeta.img
    4. fastboot flash vbmeta_system vbmeta.img
    5. fastboot flash vbmeta_vendor vbmeta.img
    6. 上面这是什么意思?
  3. 源项目(含LineageOS/cache.img/userdata.img/vbmeta.img)
  4. Recovery(这个recovery居然被官方停止维护了)
  5. 魔改版Magisk

《红米9A刷机root记录》

  1. 第一步:BL解锁
  2. 第二步:下载对应系统版本的卡刷包和adb Fastboot工具包
  3. 第三步:安装Magisk,Magisk 项目首页:The Magic Mask for Android
    1. 提取卡刷 包中的boot.img文件上传到手机中
    2. 在经过Magiskpatch后刷到ROM中
    3. 命令是fastboot flash boot xxx_patch_xxx.img
    4. 然后fastboot reload
  4. 第四步:刷入TWRP和刷入vbmeta
    1. 因为由于完整性校验的原因,第三步后手机会限入无限重启
    2. 使用命令“fastboot --disable-verity --disable-verification flash vbmeta vbmeta.img”关掉校验
    3. 不过我没试这个方法,而是靠刷入TWRP
    4. fastboot flash recovery recovery.img
    5. fastboot flash vbmeta vbmeta.img
    6. fastboot boot recovery.img

Redmi 9A Guides, News, & Discussion

Redmi 9A Questions & Answers

Droidian

  • 官网
  • State of Droidian Week 22 2021 | Droidian
    • June 1, 2021
    • stated
      • a simple daemon designed to augment existing settings and power management daemons
      • in order to support the wakelock-centered, opportunistic sleep as found in Android devices.
      • Enabling opportunistic sleep if supported
      • Acquiring or releasing wakelocks depending on display state
      • Reacting to the device's powerkey button events
    • hadess-sensorfw-proxy:方向传感器
    • phosh:A pure Wayland shell prototype for GNOME on mobile devices.
      • a pure wayland shell for mobile devices like Purism's Librem 5.
    • Volla Comunity Days 2021:参加活动,展示系统

待学资源

How to Install Custom ROM on Android to get new features on your phone

AKR社区

Linux Kernel Device Tree 配置框架_csid_502的博客-CSDN博客